# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program.  If not, see
# <http://www.gnu.org/licenses/>.

package bamp::CApiGen;
use bamp::Bamp;

sub new($)
{
    my $api = $_[1];
    my $self = { api => $api };
    bless $self;
    return $self;
}

sub arg_type($)
{
    my ($self, $arg) = @_;
    my $api = ${$self}{api};
    return defined $arg ? ${${$arg}[2]}{"C"} : "void";
}

sub meth_name($)
{
    my ($self, $method) = @_;
    my $api = ${$self}{api};
    my $name = ${$method}{name};
    return $name;
}

sub args
{
    my ($self, $method) = @_;
    my $api = ${$self}{api};

    my @args = ();
    for my $arg (@{${$method}{args}})
    {
        my $n = ${$arg}[0];
        my $d = ${$arg}[1];
        my $t = ${${$arg}[2]}{"C"};
        my $ref = ${${$arg}[4]}{"C"}{ref} ? 1 : 0;
        push @args, "$t $n"        if $d eq "in" && !$ref;
        push @args, "const $t* $n" if $d eq "in" && $ref;
        push @args, "$t* $n"       if ($d eq "out" || $d eq "io") && !$ref;
        push @args, "$t** $n"      if ($d eq "out" || $d eq "io") && $ref;
    }

    return @args;
}

sub header
{
    return $bamp::Bamp::licence;
}


sub declare($$$$)
{
    my ($self, $meth, $prefix, $ctxname, $ctxtype) = @_;
    my $api      = ${$self}{api};
    my @outs     = $api->all_out($meth);
    my $ret      = shift(@outs);
    my $rettype  = $self->arg_type($ret);
    my $methname = $self->meth_name($meth);

    # Populate argument list. Add a "context" as a first argument if
    # one has been provided.
    my @args = ();
    if (defined $ctxname && defined $ctxtype)
    {
        my $ctxdecl = "$ctxtype* $ctxname";
        $ctxdecl = "const $ctxdecl" if ${$meth}{const};
        push (@args, $ctxdecl);
    }
    push (@args, $self->args($meth));

    return "bamp_rc $prefix$methname(".join(', ', @args).")";
}

1;

